home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / sunfonts / fontutil.c < prev    next >
C/C++ Source or Header  |  1992-02-06  |  14KB  |  638 lines

  1. #include <ctype.h>
  2. #include "../src/CType.h"
  3. #include <stdio.h>
  4. #include "Font.h"
  5.  
  6. extern char *gets(), *index();
  7. extern char *strcpy();
  8.  
  9. static char *myname;    /* initialized from argv[0] */
  10. static char *currentFile;
  11. static int linenum;        /* for error messages */
  12.  
  13. char *adobename(i)
  14. int i;
  15. {
  16.     static char buf[10];
  17.     
  18.     char *s= (_C_Type_+1)[i].name;
  19.     if (s)
  20.     return s;
  21.     sprintf(buf, "C0%02x", i);
  22.     return buf;
  23. }
  24.  
  25. static char *hexChars= "0123456789abcdef";
  26.  
  27. void MaxExtent(font, xp, yp)
  28. Font *font;
  29. int *xp, *yp;
  30. {
  31.     register Glyph *gp;
  32.     register int i, width, height;
  33.     
  34.     width= height= 0;
  35.     for (i= 0; i < MAXCHARS; i++) {
  36.     if (gp= font->glyphs[i]) {
  37.         width= max(width, gp->left + gp->right);
  38.         height= max(height, gp->up + gp->down);
  39.     }
  40.     }
  41.     *xp= width;
  42.     *yp= height;
  43. }
  44.  
  45. void DumpAsBdf(ofp, font)
  46. FILE *ofp;
  47. Font *font;
  48. {
  49.     register Glyph *gp;
  50.     register byte *cp;
  51.     int nchars, i, x, y, w, h, width, height, left, down, up;
  52.     
  53.     fputs("STARTFONT 2.1\n", ofp);
  54.     for (i= 0; i < font->ncomments; i++)
  55.     fprintf(ofp, "%s\n", font->comments[i]);
  56.     fprintf(ofp, "FONT %s\n", font->name);
  57.     fprintf(ofp, "SIZE %d %d %d\n", font->size, font->resx, font->resy);
  58.     
  59.     nchars= width= height= left= down= up= 0;
  60.     for (i= 0; i < MAXCHARS; i++) {
  61.     if (gp= font->glyphs[i]) {
  62.         width= max(width, gp->left + gp->right);
  63.         height= max(height, gp->up + gp->down);
  64.         left= max(left, gp->left);
  65.         down= max(down, gp->down);
  66.         up= max(up, gp->up);
  67.         nchars++;
  68.     }
  69.     }
  70.     fprintf(ofp, "FONTBOUNDINGBOX %d %d %d %d\n", width, height, -left, -down);
  71.  
  72.     if (font->nprops+3) {
  73.     fprintf(ofp, "STARTPROPERTIES %d\n", font->nprops+3);
  74.     if (font->ascent == 9999)
  75.         font->ascent= up;
  76.     fprintf(ofp, "FONT_ASCENT %d\n", font->ascent);
  77.     if (font->descent == 9999)
  78.         font->descent= down;
  79.     fprintf(ofp, "FONT_DESCENT %d\n", font->descent);
  80.     if (font->defaultchar == 9999)
  81.         font->defaultchar= 0;
  82.     fprintf(ofp, "DEFAULT_CHAR %d\n", font->defaultchar);
  83.     for (i= 0; i < font->nprops; i++) 
  84.         fprintf(ofp, "%s\n",font->props[i]);
  85.     fputs("ENDPROPERTIES\n", ofp);
  86.     }
  87.  
  88.     fprintf(ofp, "CHARS %d\n", nchars);
  89.         
  90.     for (i= 0; i < MAXCHARS; i++) {
  91.     if ((gp= font->glyphs[i]) == 0)
  92.         continue;
  93.         
  94.     fprintf(ofp, "STARTCHAR %s\n", gp->name);
  95.     fprintf(ofp, "ENCODING %d\n", i);
  96.     fprintf(ofp, "SWIDTH %d 0\n", gp->swidth);
  97.     fprintf(ofp, "DWIDTH %d 0\n", gp->width);
  98.     w= gp->left+gp->right;
  99.     h= gp->up+gp->down;
  100.     fprintf(ofp, "BBX %d %d %d %d\n", w, h, -gp->left, -gp->down);
  101.     if (gp->attr)
  102.         fprintf(ofp, "ATTRIBUTES %04x\n", gp->attr);
  103.     fprintf(ofp, "BITMAP\n");
  104.     if (gp->nbytes && gp->bits) {
  105.         for (y= 0; y < h; y++) {
  106.         cp= &gp->bits[y*gp->bytesperline];
  107.         for (x= 0; x < gp->bytesperline; x++, cp++) {
  108.             fputc(hexChars[*cp >> 4], ofp);
  109.             fputc(hexChars[*cp & 15], ofp);
  110.         }
  111.         fputc('\n', ofp);
  112.         }
  113.     }
  114.     fputs("ENDCHAR\n", ofp);
  115.     }
  116.     fputs("ENDFONT\n", ofp);
  117. }
  118.  
  119. char *strsave(s)
  120. char *s;
  121. {
  122.     return strcpy(malloc(strlen(s)+1), s);
  123. }
  124.  
  125. void AddProp(font, s)
  126. Font *font;
  127. char *s;
  128. {
  129.     font->props[font->nprops++]= strsave(s);
  130. }
  131.  
  132. void AddComment(font, s)
  133. Font *font;
  134. char *s;
  135. {
  136.     font->comments[font->ncomments++]= strsave(s);
  137. }
  138.  
  139. Font *NewFont(name, size, resx, resy, asc, desc, dflt)
  140. char *name;
  141. int size, resx, resy, asc, desc, dflt;
  142. {
  143.     Font *fp= (Font*) malloc(sizeof (Font));
  144.     bzero(fp, sizeof (Font));
  145.     fp->props= (char**) malloc(sizeof (char*) * 10);
  146.     fp->comments= (char**) malloc(sizeof (char*) * 10);
  147.     if (name)
  148.     fp->name= strsave(name);
  149.     fp->size= size;
  150.     fp->resx= resx;
  151.     fp->resy= resy;
  152.     fp->ascent= asc;
  153.     fp->descent= desc;
  154.     fp->defaultchar= dflt;
  155.     return fp;
  156. }
  157.  
  158. AddGlyph(font, i, wd, up, down, left, right, n, bp, name, attr)
  159. Font *font;
  160. char *name;
  161. unsigned int attr;
  162. int i, wd, up, down, left, right, n;
  163. byte *bp;
  164. {
  165.     Glyph *gp;
  166.     
  167.     if (font->glyphs[i])
  168.     FreeGlyph(font->glyphs[i]);
  169.     gp= font->glyphs[i]= (Glyph*) malloc(sizeof (Glyph));
  170.     gp->attr= attr;
  171.     gp->width= wd;
  172.     gp->up= up;
  173.     gp->down= down;
  174.     gp->left= left;
  175.     gp->right= right;
  176.     gp->swidth= 666;
  177.     gp->name= name;
  178.     
  179.     gp->bytesperline= Bytes(left+right);
  180.     gp->nbytes= n;
  181.     if (n > 0 && bp != 0) {
  182.     gp->bits= (byte*) malloc(n);
  183.     bcopy(bp, gp->bits, n);
  184.     } else
  185.     gp->bits= 0;
  186. }
  187.  
  188. /*
  189.  * read the next line and keep a count for error messages
  190.  */
  191. char *getline(s)
  192. char *s;
  193. {
  194.     s= gets(s);
  195.     linenum++;
  196.     while (s) {
  197.     int len= strlen(s);
  198.     if (len && s[len-1] == '\015')
  199.         s[--len] = '\0';
  200.     if (len == 0) {
  201.         s= gets(s);
  202.         linenum++;
  203.     } else
  204.         break;
  205.     }
  206.     return s;
  207. }
  208.  
  209. /*
  210.  * return 1 if str is a prefix of buf
  211.  */
  212. int prefix(buf, str)
  213. char *buf, *str;
  214. {
  215.     return strncmp(buf, str, strlen(str)) ? 0 : 1;
  216. }
  217.  
  218. /*
  219.  * make a byte from the first two hex characters in s
  220.  */
  221. byte hexbyte(s)
  222. char *s;
  223. {
  224.     byte b = 0;
  225.     register char c;
  226.     int i;
  227.  
  228.     for (i=2; i; i--) {
  229.     c = *s++;
  230.     if (isascii(c) && isxdigit(c)) {
  231.         if (isdigit(c))
  232.         b = (b<<4) + (c - '0');
  233.         else if (isupper(c))
  234.         b = (b<<4) + 10 + (c - 'A');
  235.         else
  236.         b = (b<<4) + 10 + (c - 'a');
  237.     } else
  238.         fatal("bad hex char '%c'", c);
  239.     } 
  240.     return b;
  241. }
  242.  
  243. /*VARARGS*/
  244. warning(msg, p1, p2, p3, p4)
  245.     char *msg, *p1;
  246. {
  247.     fprintf(stderr, "%s: %s: ", myname, currentFile);
  248.     fprintf(stderr, msg, p1, p2, p3, p4);
  249.     if (linenum)
  250.     fprintf(stderr, " at line %d\n", linenum);
  251.     else
  252.     fprintf(stderr, "\n");
  253. }
  254.  
  255. /*
  256.  * fatal error. never returns.
  257.  */
  258. /*VARARGS*/
  259. fatal(msg, p1, p2, p3, p4)
  260.     char *msg, *p1;
  261. {
  262.     warning(msg, p1, p2, p3, p4);
  263.     exit(1);
  264. }
  265.  
  266. Font *ReadBdf(file)
  267. char *file;
  268. {
  269.     int nchars, nbytes, i, resx, resy, haveFontAscent, haveFontDescent;
  270.     unsigned int attributes;
  271.     char linebuf[BUFSIZ], namebuf[100], fontName[100];
  272.     byte *bp, bbuf[10000];
  273.     float size;
  274.     Font *font;
  275.     
  276.     haveFontAscent= haveFontDescent= 0;
  277.  
  278.     font= NewFont(0, 0, 0, 0, 0, 0, 0);
  279.     
  280.     currentFile= file;
  281.     
  282.     if (freopen(currentFile, "r", stdin) == NULL)
  283.     fatal("could not open file\n");
  284.  
  285.     getline(linebuf);
  286.  
  287.     if ((sscanf(linebuf, "STARTFONT %s", namebuf) != 1) || strcmp(namebuf, "2.1"))
  288.     fatal("bad 'STARTFONT'");
  289.     getline(linebuf);
  290.     
  291.     while (prefix(linebuf, "COMMENT")) {
  292.     AddComment(font, linebuf);
  293.     getline(linebuf);
  294.     }
  295.  
  296.     if (sscanf(linebuf, "FONT %[^\n]", fontName) != 1)
  297.     fatal("bad 'FONT'");
  298.     getline(linebuf);
  299.  
  300.     if (!prefix(linebuf, "SIZE"))
  301.     fatal("missing 'SIZE'");
  302.     if ((sscanf(linebuf, "SIZE %f%d%d", &size, &resx, &resy) != 3))
  303.     fatal("bad 'SIZE'");
  304.     if ((size < 1) || (resx < 1) || (resy < 1))
  305.     fatal("SIZE values must be > 0");
  306.     if (resx != resy)
  307.     fatal("x and y resolution must be equal");
  308.     getline(linebuf);
  309.  
  310.     if (!prefix(linebuf, "FONTBOUNDINGBOX"))
  311.     fatal("missing 'FONTBOUNDINGBOX'");
  312.     getline(linebuf);
  313.  
  314.     font->name= strsave(fontName);
  315.     font->size= (int)size;
  316.     font->resx= resx;
  317.     font->resy= resy;
  318.  
  319.     if (prefix(linebuf, "STARTPROPERTIES")) {
  320.     int nprops;
  321.  
  322.     if (sscanf(linebuf, "STARTPROPERTIES %d", &nprops) != 1)
  323.        fatal("bad 'STARTPROPERTIES'");
  324.        
  325.     getline(linebuf);
  326.     AddProp(font, linebuf);
  327.     while((nprops-- > 0) && !prefix(linebuf, "ENDPROPERTIES")) {
  328.         getline(linebuf);
  329.         if (nprops > 0)
  330.         AddProp(font, linebuf);
  331.     }
  332.     if (!prefix(linebuf, "ENDPROPERTIES"))
  333.         fatal("missing 'ENDPROPERTIES'");
  334.     /*
  335.     if (!haveFontAscent || !haveFontDescent)
  336.         fatal("must have 'FONT_ASCENT' and 'FONT_DESCENT' properties");
  337.     */
  338.     if (nprops != -1)
  339.         fatal("%d too few properties", nprops+1);
  340.         
  341.     } else /* no properties */
  342.     fatal("missing 'STARTPROPERTIES'");
  343.     getline(linebuf);
  344.  
  345.     if (sscanf(linebuf, "CHARS %d", &nchars) != 1)
  346.     fatal("bad 'CHARS'");
  347.     if (nchars < 1)
  348.     fatal("invalid number of CHARS");
  349.     getline(linebuf);
  350.  
  351.     while ((nchars-- > 0) && prefix(linebuf, "STARTCHAR"))  {
  352.     int t, ix, wx, wy, bw, bh, bl, bb, enc, enc2, bytesperrow, row;
  353.     char *p, charName[100];
  354.  
  355.     if (sscanf(linebuf, "STARTCHAR %s", charName) != 1)
  356.         fatal("bad character name");
  357.  
  358.     getline(linebuf);
  359.     if ((t=sscanf(linebuf, "ENCODING %d %d", &enc, &enc2)) < 1)
  360.         fatal("bad 'ENCODING'");
  361.     if ((enc < -1) || ((t == 2) && (enc2 < -1)))
  362.         fatal("bad ENCODING value");
  363.     if (t == 2 && enc == -1)
  364.         enc = enc2;
  365.     if (enc == -1) {
  366.         warning("character '%s' ignored\n", charName);
  367.         do {
  368.         char *s = getline(linebuf);
  369.         if (!s)
  370.             fatal("Unexpected EOF");
  371.         } while (!prefix(linebuf, "ENDCHAR"));
  372.         getline(linebuf);
  373.         continue;
  374.     }
  375.     if (enc >= MAXCHARS)
  376.         fatal("character '%s' has encoding(=%d) too large", charName, enc);
  377.  
  378.     getline(linebuf);
  379.     if (sscanf( linebuf, "SWIDTH %d %d", &wx, &wy) != 2)
  380.         fatal("bad 'SWIDTH'");
  381.     if (wy != 0)
  382.         fatal("SWIDTH y value must be zero");
  383.  
  384.     getline(linebuf);
  385.     if (sscanf( linebuf, "DWIDTH %d %d", &wx, &wy) != 2)
  386.         fatal("bad 'DWIDTH'");
  387.     if (wy != 0)
  388.         fatal("DWIDTH y value must be zero");
  389.  
  390.     getline(linebuf);
  391.     if (sscanf( linebuf, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)
  392.         fatal("bad 'BBX'");
  393.     if (bh < 0 || bw < 0)
  394.         fatal("character '%s' has a negative sized bitmap, %dx%d", charName, bw, bh);
  395.  
  396.     getline(linebuf);
  397.     if (prefix(linebuf, "ATTRIBUTES")) {
  398.         for (p= linebuf + strlen("ATTRIBUTES "); (*p == ' ') || (*p == '\t');
  399.         p++)
  400.         /* empty for loop */ ;
  401.         attributes = hexbyte(p)<< 8 + hexbyte(p+2);
  402.         getline(linebuf);  /* set up for BITMAP which follows */
  403.     } else
  404.         attributes= 0;
  405.     if (!prefix(linebuf, "BITMAP"))
  406.         fatal("missing 'BITMAP'");
  407.  
  408.     bytesperrow = Bytes(bw);
  409.     nbytes= bytesperrow * bh;
  410.     bp= bbuf;
  411.     for (row= 0; row < bh; row++) {
  412.         getline(linebuf);
  413.         p = linebuf;
  414.         if (strlen(p) & 1)
  415.         fatal("odd number of characters in hex encoding");
  416.         for (ix= 0; ix < bytesperrow; ix++, p+=2)
  417.         *bp++= hexbyte(p);
  418.     }
  419.     getline(linebuf);
  420.     if (!prefix(linebuf, "ENDCHAR"))
  421.         fatal("missing 'ENDCHAR'");
  422.     AddGlyph(font, enc, wx, bh+bb, -bb, -bl, bw+bl, nbytes, bbuf, charName, attributes);
  423.     getline(linebuf);              /* get STARTCHAR or ENDFONT */
  424.     }
  425.  
  426.     if (nchars != -1)
  427.     fatal("%d too few characters", nchars+1);
  428.     if (prefix(linebuf, "STARTCHAR"))
  429.     fatal("more characters than specified");
  430.     if (!prefix(linebuf, "ENDFONT"))
  431.     fatal("missing 'ENDFONT'");
  432.     if (nchars != -1)
  433.     fatal("%d too few characters", nchars+1);
  434. /*
  435.     if (nGl == 0)
  436.     fatal("No characters with valid encodings");
  437. */
  438.     return font;
  439. }
  440.  
  441. void FreeGlyph(gp)
  442. Glyph *gp;
  443. {
  444.     if (gp->bits)
  445.     free(gp->bits);
  446.     free(gp);
  447. }
  448.  
  449. void FreeFont(font)
  450. Font *font;
  451. {
  452.     register int i;
  453.     
  454.     if (font == 0)
  455.     return;
  456.     
  457.     for (i= 0; i < MAXCHARS; i++)
  458.     if (font->glyphs[i])
  459.          FreeGlyph(font->glyphs[i]);
  460.     if (font->props) {
  461.     for (i= 0; i < font->nprops; i++) 
  462.         if (font->props[i])
  463.         free(font->props[i]);
  464.     free(font->props);
  465.     }
  466.     if (font->ncomments) {
  467.     for (i= 0; i < font->ncomments; i++) 
  468.         if (font->comments[i])
  469.         free(font->comments[i]);
  470.     free(font->comments);
  471.     }
  472.     if (font->name)
  473.     free(font->name);
  474.     free(font);
  475. }
  476.  
  477. unsigned int mask[]= { 128, 64, 32, 16, 8, 4, 2, 1 };
  478.  
  479. BitBlt(to, tobytesperline, tox, toy, from, frobytesperline, fromx, fromy, w, h)
  480. byte *to, *from;
  481. int tobytesperline, frobytesperline, tox, toy, fromx, fromy, w, h;
  482. {
  483.     register int x, y;
  484.     
  485.     for (y= 0; y < h; y++)
  486.     for (x= 0; x < w; x++)
  487.         if (getbit(from, frobytesperline, fromx+x, fromy+y))
  488.         putbit(to, tobytesperline, tox+x, toy+y);
  489. }
  490.  
  491. void GlyphBBox(font, i)
  492. Font *font;
  493. int i;
  494. {
  495.     register Glyph *glyph;
  496.     register byte *cp;
  497.     register int x, y, ox, oy, w, h, down, right;
  498.     int nbytes, tobytesperline, bytesperline, wd, ht;
  499.     byte buf[1000], bbuf[10000];
  500.     
  501.     if ((glyph= font->glyphs[i]) == 0)
  502.     return;
  503.     
  504.     cp= glyph->bits;
  505.     bytesperline= glyph->bytesperline;
  506.     wd= glyph->left+glyph->right;
  507.     ht= glyph->up+glyph->down;
  508.     
  509.     for (y= 0; y < ht; y++)
  510.     for (x= 0; x < wd; x++)
  511.         if (getbit(cp, bytesperline, x, y))
  512.         goto out;
  513. out:
  514.     oy= y;
  515.     
  516.     for (y= ht-1; y >= 0; y--)
  517.     for (x= 0; x < wd; x++)
  518.         if (getbit(cp, bytesperline, x, y))
  519.         goto out2;
  520. out2:
  521.     h= y-oy+1;
  522.     down= ht-1-y;
  523.     
  524.     bzero(buf, bytesperline);
  525.     for (y= oy; y < oy+h+1; y++)
  526.     for (x= 0; x < bytesperline; x++)
  527.         buf[x] |= cp[y*bytesperline+x];
  528.         
  529.     for (x= 0; x < wd; x++)
  530.     if (getbit(buf, 0, x, 0))
  531.         break;
  532.     ox= x;
  533.     
  534.     for (x= wd-1; x >= 0; x--)
  535.     if (getbit(buf, 0, x, 0))
  536.         break;
  537.     w= x-ox+1;
  538.     right= wd-1-x;
  539.     
  540.     if (w < 0 || h < 0) {
  541.     AddGlyph(font, i, glyph->width, 0, 0, 0, 0, 0, 0, glyph->name, glyph->attr);
  542.     } else {
  543.     tobytesperline= Bytes(w);
  544.     nbytes= tobytesperline * h;
  545.     bzero(bbuf, nbytes);
  546.     BitBlt(bbuf, tobytesperline, 0, 0, glyph->bits, bytesperline, ox, oy, w, h);
  547.     AddGlyph(font, i, glyph->width, glyph->up-oy, glyph->down-down, glyph->left-ox,
  548.                 glyph->right-right, nbytes, bbuf, glyph->name, glyph->attr);
  549.     }
  550. }
  551.  
  552. void FontBBox(font)
  553. Font *font;
  554. {
  555.     register int i;
  556.     
  557.     if (font == 0)
  558.     return;
  559.     
  560.     for (i= 0; i < MAXCHARS; i++)
  561.     GlyphBBox(font, i);
  562. }
  563.  
  564. void RemoveGlyph(font, i)
  565. Font *font;
  566. int i;
  567. {
  568.     if (font && font->glyphs[i]) {
  569.     FreeGlyph(font->glyphs[i]);
  570.     font->glyphs[i]= 0;
  571.     }
  572. }
  573.  
  574. void Encode(font)
  575. Font *font;
  576. {
  577.     RemoveGlyph(font, 176);
  578.     RemoveGlyph(font, 177);
  579.     RemoveGlyph(font, 178);
  580.     RemoveGlyph(font, 179);
  581.     RemoveGlyph(font, 181);
  582.     RemoveGlyph(font, 182);
  583.     RemoveGlyph(font, 183);
  584.     RemoveGlyph(font, 184);
  585.     RemoveGlyph(font, 185);
  586.     RemoveGlyph(font, 186);
  587.     RemoveGlyph(font, 189);
  588.     RemoveGlyph(font, 195);
  589.     RemoveGlyph(font, 196);
  590.     RemoveGlyph(font, 197);
  591.     RemoveGlyph(font, 198);
  592.     RemoveGlyph(font, 215);
  593.     RemoveGlyph(font, 218);
  594.     RemoveGlyph(font, 240);
  595. }
  596.  
  597. int IsFixed(font)
  598. Font *font;
  599. {
  600.     int i, w;
  601.     Glyph *gp;
  602.     
  603.     gp= font->glyphs['a'];
  604.     if (gp) {
  605.     w= gp->width;
  606.     for (i= 'b'; i < 'z'; i++)
  607.         if (gp= font->glyphs[i])
  608.         if (gp->width != w)
  609.             return 0;
  610.     for (i= 'A'; i < 'Z'; i++)
  611.         if (gp= font->glyphs[i])
  612.         if (gp->width != w)
  613.             return 0;
  614.     }
  615.     return 1;
  616. }
  617.  
  618. Clean(font)
  619. Font *font;
  620. {
  621.     int i, w;
  622.     Glyph *gp;
  623.     
  624.     w= font->glyphs['a']->width;
  625.     for (i= 0; i < MAXCHARS; i++) {
  626.     if (gp= font->glyphs[i]) {
  627.         if (gp->left > 0 || (gp->left+gp->right > w)) {
  628.         fprintf(stderr, "removing: %s\n", adobename(i));
  629.         FreeGlyph(font->glyphs[i]);
  630.         font->glyphs[i]= 0;
  631.         } else
  632.         gp->width= w;
  633.     }
  634.     }
  635. }
  636.  
  637.  
  638.